/* 
 * File:   Shape.h
 * Author: RedEyedKiller
 *
 * Created on 20 Απρίλιος 2010, 3:13 πμ
 */

#ifndef _SHAPE_H
#define	_SHAPE_H

#include "Mathematics.h"
#include "Vector2.h"

namespace Math
{
/*The root class of the Shape hierarchy*/

class Shape
{
public:

    virtual ~Shape()
    {
    }

    virtual Shape* Clone() = 0;
    /*returns the center of the shape*/
    virtual Vector2F GetCenter() const = 0;
    virtual void SetCenter(const Vector2F& center) = 0;
    /*
    virtual Vector2I GetOrigin() const = 0;
    virtual void SetOrigin(Vector2I& center) = 0;
    virtual void SetOrigin(int x,int y) = 0;
     */

    /* Methods which return the distance between this' center and other shapes'
     * center*/
    float DistanceCenter(const Shape& shape) const
    {
        return (this->GetCenter().Distance(shape.GetCenter()));
    }

    float DistanceCenter(const Vector2I& vect) const
    {
        return (this->GetCenter().Distance(vect));
    }

    /* Methods which return the distance between this and other shapes*/
    virtual Vector2Templ<float> DistanceClosestPoint(const Shape& shape) const = 0;
    virtual Vector2Templ<float> DistanceClosestPoint(const Vector2F& vect) const = 0;

    /*return true if this intersects with shape*/
    virtual bool Intersect(const Shape& shape) const = 0;
    virtual bool Intersect(const Vector2I& vec) const = 0;
    virtual bool Intersect(const Vector2F& vec) const = 0;

    /*the extented Intersection method proxies*/
    /*for more info look @ Math.h */
    virtual IntersectionType Intersect(const Shape& shape, Vector2Templ<float>& axisInfo)const = 0 ;

    /*returns the total area that this shape holds*/
    virtual float CalculateArea()const = 0;
public:
    /* This set of methods is used in order to achive double dispatching.
     * This is achieved by 2 sequential method calls in order to determine
     * the exact type of the two abstract object pointers which are ivolved.
     * ex.
     * In run time shape1->Foo(shape2); the implementation of Foo(...) depends on
     * the type of shape1. If it is a circle Circle::Foo(...) wil be called etc.
     * In Foo(..)'s body ( for very concrete class of shape hierarchy ), there
     * is a call to shape2->FooWith( *this ).
     * FooWith(...) is an overloaded method which handles every subclass of Shape.
     * Because it is inside the implementation of ConcreteClass::Foo() the exact
     * type of this can be determined in compile time an thus a diffrent implementation
     * of FooWith() is called. So the result of Foo() depends not only on the concrete type
     * of the caller Shape but on the concrete type of the Shape argument too.
     */
    virtual bool IntersectWith(const Circle& circle)const = 0;
    virtual bool IntersectWith(const Rect& rect) const = 0;
    virtual IntersectionType IntersectWith(const Circle& circle, Vector2Templ<float>& axisInfo)const = 0;
    virtual IntersectionType IntersectWith(const Rect& rect, Vector2Templ<float>& axisInfo)const = 0;
    virtual Vector2Templ<float> DistanceClosestPointFrom(const Rect& rect) const = 0;
    virtual Vector2Templ<float> DistanceClosestPointFrom(const Circle& circle) const = 0;
};

}

#endif	/* _SHAPE_H */

